/*
目录是一个树状结构，在遍历时一般使用深度优先+先序遍历算法
深度优先，意味着到达一个节点后，首先接着遍历子节点而不是邻居节点
先序遍历，意味着首次到达了某节点就算遍历完成，而不是最后一次返回某节点才算数
因此使用这种遍历方式时，下边这棵树的遍历顺序是A > B > D > E > C > F。
        A
       / \
      B   C
     / \   \
    D   E   F
*/


//fs.rname fs.unlink
//fs.access 判断文件是否可访问
//fs.stat 判断文件装填
//fs.mkdir fs.rmdir
//fs.readdir

const path = require('path');
const resolve = (filename) => {
  return path.resolve(__dirname, filename);
};

// const fs = require('fs');
let pathUrl = 'a/b/c/d/e'; //mac下是/  windows下是\

//mkdir不能递归重建目录
/*const mkdirSync = (pathUrl) => {
  let pathArr = pathUrl.split('/');
  for(let i=0;i<pathArr.length;++i){
    let current = pathArr.slice(0, i + 1).join('/');
    try {
      fs.accessSync(current);
    }catch (e) {
      fs.mkdirSync(current);
    }
  }
};
mkdirSync(pathUrl);*/





//异步创建
/*
const mkdir = (pathUrl,cb) => {
  let pathArr = pathUrl.split('/');
  function next(index){
    if(index === pathArr.length) return cb;
    const current = pathArr.slice(0, ++index).join('/');
    fs.access(current, (err, data) => {
      if(err){
        fs.mkdir(current,()=>{
          next(index);
        })
      }else{ // 如果存在，创建下一层
        next(index);
      }
    });
  }
  next(0)
};
mkdir(pathUrl, (err, data) => {
  console.log('成功');
});
*/




//删除
// fs.rmdirSync('a'); //Error: ENOTEMPTY: directory not empty, rmdir 'a'

//虽然是递归，但我们只用考虑两层的时候是怎么处理的，逻辑是一样的

//深度同步遍历
/*const rmdirSync = (filePath) => {
  console.log('filePath:',filePath);
  let statObj = fs.statSync(filePath);
  console.log('statObj.isDirectory:',statObj.isDirectory);
  if(statObj.isDirectory()){
    let dirs = fs.readdirSync(filePath); //读取儿子目录
    dirs = dirs.map(dir => path.join(filePath, dir));
    dirs.forEach(dir => {
      rmdirSync(dir);
    });
    fs.rmdirSync(filePath); //再去删除自己
  }else{
    fs.unlinkSync(filePath); //如果是文件删除即可
  }
};

rmdirSync('a');*/



//深度异步遍历 异步串行
/*
const removeDir = (filepath, callback) => {
  fs.stat(filepath, function (err, statObj) {
    if(statObj.isDirectory()){
      fs.readdir(filepath, function (err, dirs) {
        dirs = dirs.map(dir => path.join(filepath, dir));
        let index = 0;
        function next(){
          if(index === dirs.length) return fs.rmdir(filepath, callback);
          let currentDir = dirs[index++];
          removeDir(currentDir, () => next());
        }
        next();
      });

    }else{
      fs.unlink(filepath,callback);
    }
  });
};
*/


//深度 异步并发 paralle
/*
const removeDir = (filepath, callback) => {
  fs.stat(filepath, function (err, statObj) {
    if(statObj.isDirectory()){
      fs.readdir(filepath, function (err, dirs) {
        dirs = dirs.map(dir => path.join(filepath, dir));
        if(dirs.length === 0) fs.rmdir(filepath, callback); //如果是空文件夹 直接删除即可
        let index = 0;
        let done = () => { // 如果删除的个数和儿子的个数相同 说明儿子已删除完毕 该删除父亲了
          if(++index === dirs.length){
            return fs.rmdir(filepath, callback);
          }
        };
        for (let i = 0; i < dirs.length; ++i) {
          removeDir(dirs[i],done);
        }
      });
    }else{
      fs.unlink(filepath,callback);
    }
  });
};
*/



/*
removeDir('a',()=>{
  console.log('删除成功');
});
*/

/*const fs = require('fs').promises;

const removeDir = async filePath => {
  let statObj = await fs.stat(filePath);
  if(statObj.isDirectory()){
    const dirs = await fs.readdir(filePath);
    const ps = dirs.map(dir => removeDir(path.join(filePath, dir)));
    await Promise.all(ps);
    await fs.rmdir(filePath);
  }else{
    await fs.unlink(filePath);
  }
};

removeDir('a').then(data => {
  console.log('成功');
});*/





//广度优先
/*const fs = require('fs');
function rmSync(dir){
  let arr=[dir];
  let index=0;
  while (arr[index]) {
    let current=arr[index++];
    let stat=fs.statSync(current);
    if (stat.isDirectory()) {
      let dirs=fs.readdirSync(current);
      arr=[...arr,...dirs.map(d => path.join(current,d))];
    }
  }
  let item;
  while (undefined !== (item = arr.pop())) {
    let stat = fs.statSync(item);
    if (stat.isDirectory()) {
      fs.rmdirSync(item);
    } else {
      fs.unlinkSync(item);
    }
  }
}
rmSync('a');*/

//异步删除目录(广度优先)
const fs = require('fs');
function rmdirWideAsync(dir,callback){
  let dirs=[dir];
  let index=0;
  function rmdir() {
    let current = dirs.pop();
    if (current) {
      fs.stat(current,(err,stat) => {
        if (stat.isDirectory()) {
          fs.rmdir(current,rmdir); //递归
        } else {
          fs.unlink(current,rmdir);
        }
      });
    }
  }
  //自执行
  !function next() {
    let current=dirs[index++];
    if (current) {
      fs.stat(current,(err,stat) => {
        if (err) callback(err);
        if (stat.isDirectory()) {
          fs.readdir(current,(err,files) => {
            dirs=[...dirs,...files.map(item => path.join(current,item))];
            next();
          });
        } else {
          next();
        }
      });
    } else {
      rmdir();
    }
  }();

}
rmdirWideAsync('a')
